package com.common.utils;

import cn.hutool.core.lang.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

/**
 * 配置文件读取工具
 *
 * @author xin.ding
 * @date 2020/10/17 10:52
 */
public class PropertiesUtils {

    /** logger */
    private static final Logger log = LoggerFactory.getLogger(PropertiesUtils.class);

    /** 配置属性文件 */
    private static final String DEFAULT_CONFIG = "config.properties";

    /** 默认配置文件路径 */
    private static final String DEFAULT_PATH = System.getProperty("user.dir") + File.separator + DEFAULT_CONFIG;

    /** log4j配置文件 */
    private static final String LOG4J_CONFIG = "log4j.properties";

    /** log4j2配置文件 */
    private static final String LOG4J2_CONFIG = "log4j2.xml";

    /** Properties */
    private static Properties properties = new Properties();

    /**
     * 获取配置信息
     *
     * @return Properties
     */
    public static Properties getProperties() {
        return properties;
    }


    static {
        loadProperties(DEFAULT_PATH);
    }

    /**
     * 加载配置文件
     *
     * @param configPath 配置文件路径
     * @return Properties
     */
    private static void loadProperties(String configPath) {
        try {
            File file = new File(configPath);

            InputStream inputStream = null;
            if (file.exists()) {
                log.info("Load 'config.properties' file in {}", configPath);
                inputStream = new FileInputStream(new File(configPath));
            } else {
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                URL url = (classLoader != null ? classLoader.getResource(DEFAULT_CONFIG) :
                        ClassLoader.getSystemResource(DEFAULT_CONFIG));
                if (url != null) {
                    log.info("Load 'config.properties' file in local classpath");
                    inputStream = url.openStream();
                }

                if (inputStream == null) {
                    assert classLoader != null;
                    log.info("try to load 'config.properties' in getResourceAsStream way");
                    inputStream = classLoader.getResourceAsStream(DEFAULT_CONFIG);
                }
            }
            properties.load(inputStream);
            Assert.notNull(properties, "properties is null！");
        } catch (IOException ex) {
            log.info("Could not load 'config.properties' file: {}", ex.getMessage());
        }
    }

    public static String getString(String key) {
        return getProperties().getProperty(key);
    }

    public static String getString(String key, String defaultValue) {
        return getProperties().getProperty(key, defaultValue);
    }

    public static void setProperties(String key, String value) {
        getProperties().setProperty(key, value);
    }

    public static boolean getBoolean(String key) {
        return Boolean.parseBoolean(getProperties().getProperty(key));
    }


    /**
     * 获取配置文件int类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static Integer getInteger(Properties properties, String key) {
        try {
            return Integer.parseInt(properties.getProperty(key));
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 获取配置文件Long类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static Long getLong(Properties properties, String key) {
        try {
            return Long.parseLong(properties.getProperty(key));
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 获取配置文件Long类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static Boolean getBoolean(Properties properties, String key) {
        try {
            return Boolean.parseBoolean(properties.getProperty(key));
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 获取配置文件String类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static String getString(Properties properties, String key) {
        try {
            return properties.getProperty(key);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 获取配置文件int类型值
     *
     * @param properties   properties
     * @param key          key值
     * @param defaultValue 默认值
     */
    public static int getInteger(Properties properties, String key, int defaultValue) {
        try {
            return Integer.parseInt(properties.getProperty(key));
        } catch (Exception e) {
            return defaultValue;
        }


    }

    /**
     * 获取配置文件Long类型值
     *
     * @param properties   properties
     * @param key          key值
     * @param defaultValue 默认值
     */
    public static long getLong(Properties properties, String key, long defaultValue) {
        try {
            return Long.parseLong(properties.getProperty(key));
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 获取配置文件int类型值
     *
     * @param properties   properties
     * @param key          key值
     * @param defaultValue 默认值
     */
    public static String getString(Properties properties, String key, String defaultValue) {
        try {
            return properties.getProperty(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }


    // ===============================验证准确性=================================

    /**
     * 获取String类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static String getStringValidate(Properties properties, String key) {
        if (!properties.containsKey(key)) {
            throw new CommonException("Properties中不包含key:{}", key);
        }
        return properties.getProperty(key);
    }

    /**
     * 获取int类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static int getIntegerValidate(Properties properties, String key) {
        if (!properties.containsKey(key)) {
            throw new CommonException("Properties中不包含key:{}", key);
        }

        try {
            return Integer.parseInt(String.valueOf(properties.get(key)));
        } catch (Exception e) {
            throw new CommonException("Properties获取Integer失败,{}" + e.getMessage());
        }
    }


    /**
     * 获取long类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static Long getLongValidate(Properties properties, String key) {
        if (!properties.containsKey(key)) {
            throw new CommonException("Properties中不包含key:{}", key);
        }

        try {
            return Long.parseLong(String.valueOf(properties.get(key)));
        } catch (Exception e) {
            throw new CommonException("Properties获取Long失败,{}" + e.getMessage());
        }
    }

    /**
     * 获取Boolean类型值
     *
     * @param properties properties
     * @param key        key值
     */
    public static boolean getBooleanValidate(Properties properties, String key) {
        if (!properties.containsKey(key)) {
            throw new CommonException("Properties中不包含key:{}", key);
        }

        try {
            return Boolean.parseBoolean(String.valueOf(properties.get(key)));
        } catch (Exception e) {
            throw new CommonException("Properties获取Boolean失败,{}" + e.getMessage());
        }
    }

    public static int getInt(Properties config, String key, int defaultValue) {
        String val = config.getProperty(key);
        if (val == null) {
            return defaultValue;
        } else {
            try {
                return Integer.parseInt(val);
            } catch (NumberFormatException nfe) {
                throw new IllegalArgumentException(
                        "Value for configuration key='"
                                + key
                                + "' is not set correctly. "
                                + "Entered value='"
                                + val
                                + "'. Default value='"
                                + defaultValue
                                + "'");
            }
        }
    }

    /**
     * Get long from properties. This method throws an exception if the long is not valid.
     *
     * @param config       Properties
     * @param key          key in Properties
     * @param defaultValue default value if value is not set
     * @return default or value of key
     */
    public static long getLong(Properties config, String key, long defaultValue) {
        String val = config.getProperty(key);
        if (val == null) {
            return defaultValue;
        } else {
            try {
                return Long.parseLong(val);
            } catch (NumberFormatException nfe) {
                throw new IllegalArgumentException(
                        "Value for configuration key='"
                                + key
                                + "' is not set correctly. "
                                + "Entered value='"
                                + val
                                + "'. Default value='"
                                + defaultValue
                                + "'");
            }
        }
    }

    /**
     * Get long from properties. This method only logs if the long is not valid.
     *
     * @param config       Properties
     * @param key          key in Properties
     * @param defaultValue default value if value is not set
     * @return default or value of key
     */
    public static long getLong(Properties config, String key, long defaultValue, Logger logger) {
        try {
            return getLong(config, key, defaultValue);
        } catch (IllegalArgumentException iae) {
            logger.warn(iae.getMessage());
            return defaultValue;
        }
    }

    /**
     * Get boolean from properties. This method returns {@code true} iff the parsed value is "true".
     *
     * @param config       Properties
     * @param key          key in Properties
     * @param defaultValue default value if value is not set
     * @return default or value of key
     */
    public static boolean getBoolean(Properties config, String key, boolean defaultValue) {
        String val = config.getProperty(key);
        if (val == null) {
            return defaultValue;
        } else {
            return Boolean.parseBoolean(val);
        }
    }


    public static void main(String[] args) {
        System.out.println("Key:a,Value:" + PropertiesUtils.getString("a"));
        PropertiesUtils.setProperties("a", "test");
        System.out.println("Key:a,Value:" + PropertiesUtils.getString("a"));
    }
}
